using System.Collections.Concurrent;
using TrackSystem.IO.Utils;

namespace TrackSystem.IO.Formula
{
    public class KeywordDef
    {
        /// <summary>
        /// 标识符
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 关键字
        /// </summary>
        public string Keyword { get; set; } = "";

        /// <summary>
        /// 优先级
        /// </summary>
        public OperatorType Level { get; set; } 

        /// <summary>
        /// 操作数
        /// </summary>
        public int OpNum { get; set; } = 0;

        /// <summary>
        /// 相关的处理函数
        /// </summary>
        public Func<OperandDef[], Guid, OperandDef>? HandleFunc { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public KeywordDef()
        {
            Id = Guid.NewGuid();
            Keyword = "";
            Level = OperatorType.NONE;
            OpNum = 0;
            HandleFunc = null;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="keyword">关键字字符</param>
        /// <param name="level">运算符</param>
        /// <param name="opNum">运算数据的数目</param>
        /// <param name="handleFunc">运算函数</param>
        public KeywordDef(string keyword, OperatorType level, int opNum, Func<OperandDef[], Guid, OperandDef>? handleFunc)
        {
            Id = Guid.NewGuid();
            Keyword = keyword;
            Level = level;
            OpNum = opNum;
            HandleFunc = handleFunc;
        }
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// 关键字字典定义类
    /// </summary>
    public class KeywordsHelper
    {
        public readonly static KeywordsHelper Instance;

        public ConcurrentDictionary<OperatorType, KeywordDef> Items;
        public ConcurrentDictionary<string, KeywordDef> sKeys;

        /// <summary>
        /// 构造函数
        /// </summary>
        static KeywordsHelper()
        {
            Instance = new KeywordsHelper();
            Instance.CreateInstance();
        }

        /// <summary>
        /// 添加新的关键字
        /// </summary>
        /// <param name="keyword">关键字</param>
        /// <returns></returns>
        public bool Insert(KeywordDef keyword)
        {
            return Items.TryAdd(keyword.Level, keyword);
        }

        /// <summary>
        /// 插入计算方法
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="level"></param>
        /// <param name="opNum"></param>
        /// <param name="handleFunc"></param>
        /// <returns></returns>
        public bool Insert(string keyword, OperatorType level, int opNum, Func<OperandDef[], Guid, OperandDef>? handleFunc)
        {
            var item = new KeywordDef(keyword, level, opNum, handleFunc);
            var result = Items.TryAdd(item.Level, item);
            if (!string.IsNullOrEmpty(keyword))
                sKeys.TryAdd(item.Keyword, item);
            return result;
        }

        /// <summary>
        /// 根据关键获取关键字
        /// </summary>
        /// <param name="op"></param>
        /// <param name="keyword"></param>
        /// <returns></returns>
        public bool TryGet(OperatorType op, out KeywordDef keyword)
        {
            return Items.TryGetValue(op, out keyword);
        }

        /// <summary>
        /// 创建计算实例
        /// </summary>
        private void CreateInstance()
        {
            Items = new ConcurrentDictionary<OperatorType, KeywordDef>();
            sKeys = new ConcurrentDictionary<string, KeywordDef>();

            // 四元运算  2个
            Insert("dist", OperatorType.DIST, 4, (num, _) => ClacDef.Distance_Func(num));
            Insert("azim", OperatorType.AZIM, 4, (num, _) => ClacDef.Azimuth_Func(num));
            
            // 三元运算 2个
            Insert(":", OperatorType.COLON, 3, (num, _) => ClacDef.Colon_Func(num));
            Insert("?", OperatorType.QUESTION, 1, (num, _) => ClacDef.Question_Func(num));
            
            // 二元运算 15个
            Insert("^", OperatorType.POW, 2, (num, _) => num[1] ^ num[0]);
            Insert("+", OperatorType.ADD, 2, (num, _) => num[1] + num[0]);
            Insert("-", OperatorType.SUB, 2, (num, _) => num[1] - num[0]);
            Insert("*", OperatorType.MUL, 2, (num, _) => num[1] * num[0]);
            Insert("/", OperatorType.DIV, 2, (num, _) => num[1] / num[0]);
            Insert("%", OperatorType.MOD, 2, (num, _) => num[1] % num[0]);
            Insert("&&", OperatorType.AND, 2, (num, _) => ClacDef.LogicClac_Func(num, OperatorType.AND));
            Insert("||", OperatorType.OR, 2, (num, _) => ClacDef.LogicClac_Func(num, OperatorType.OR));
            Insert(">", OperatorType.GT, 2, (num, _) => num[1] > num[0]);
            Insert(">=", OperatorType.GE, 2, (num, _) => num[1] >= num[0]);
            Insert("<", OperatorType.LT, 2, (num, _) => num[1] < num[0]);
            Insert("<=", OperatorType.LE, 2, (num, _) => num[1] <= num[0]);
            Insert("==", OperatorType.ET, 2, (num, _) => num[1] == num[0]);
            Insert("!=", OperatorType.UT, 2, (num, _) => num[1] != num[0]);

            // 一元运算 12个
            Insert("tan", OperatorType.TAN, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.TAN));
            Insert("atan", OperatorType.ATAN, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.ATAN));
            Insert("sin", OperatorType.SIN, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.SIN));
            Insert("asin", OperatorType.ASIN, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.ASIN));
            Insert("cos", OperatorType.COS, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.COS));
            Insert("acos", OperatorType.ACOS, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.ACOS));
            Insert("abs", OperatorType.ABS, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.ABS));
            Insert("sqrt", OperatorType.SQRT, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.SQRT));
            Insert("rand", OperatorType.RAND, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.RAND));
            Insert("lg", OperatorType.LG, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.LG));
            Insert("int", OperatorType.INT, 1, (num, _) => ClacDef.MathClac_Func(num, OperatorType.INT));
            Insert("!", OperatorType.NOT, 1, (a, _) => !a[0]);
 
            // 特殊不需要运算的符号 5个
            Insert("(", OperatorType.LB, 0, null);
            Insert(")", OperatorType.RB, 0, null);
            Insert("!+", OperatorType.PS, 1, (num, _) => num[0]);
            Insert("!-", OperatorType.NS, 1, (num, _) => -num[0]);

            Insert("@", OperatorType.END, 0, null);
            
            // 添加自定义函数
            Insert("pow2", OperatorType.USERDEF, 1, (num, _) => num[0]*num[0]);
            Insert("double", OperatorType.USERDEF, 1, (num, _) => num[0] + num[0]);
            Insert("substr", OperatorType.USERDEF, 3, (num, _) => ClacDef.Substr_Func(num));

            // 特殊运算  需要保存中间状态 3个
            // Insert("ramp", OperatorType.RAMP, 2, (num, id) => FormulaTools.Instance.Step(num, id, OperatorType.RAMP));
            // Insert("angle", OperatorType.ANGLE, 2, (num, id) => FormulaTools.Instance.Step(num, id, OperatorType.RAMP));
            // Insert("filter", OperatorType.FILTER, 2, (num, id) => FormulaTools.Instance.Step(num, id, OperatorType.FILTER));
            // Insert("speed", OperatorType.SPEED, 1, (num, id) => FormulaTools.Instance.Step(num, id, OperatorType.SPEED));
        }
    }
}
